package com.yeyks.apppay.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.yeyks.apppay.config.AlipayAppConfig;
import com.yeyks.apppay.service.AlipayService;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.RefundRequestNo;
import com.yeyks.util.FormatUtils;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.RefundRequestNo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * @Author fuchangshuai
 * @date 2019/3/6 9:22 AM
 */
@Service
@Slf4j
public class AliPayServiceImpl implements AlipayService {

    @Autowired
    private AlipayAppConfig alipayAppConfig;
    private AlipayClient alipayClient;

    @PostConstruct
    public void init() {
        alipayClient = new DefaultAlipayClient(alipayAppConfig.getUrl(),
                alipayAppConfig.getAppId(),
                alipayAppConfig.getPrivateKey(),
                alipayAppConfig.getFormat(),
                alipayAppConfig.getCharset(),
                alipayAppConfig.getPubKey(),
                alipayAppConfig.getSignType());
    }

    @Override
    public String tradeAppPay(String orderNo, Integer totalFee) {
        log.info("支付宝app支付");
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content）
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("app支付");
        model.setSubject("橙果夜鱼快宿");
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(FormatUtils.fenToYuan(totalFee));
        request.setBizModel(model);
        request.setNotifyUrl(alipayAppConfig.getNotifyUrl());
        AlipayTradeAppPayResponse response;
        try {
            response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            log.error("支付宝支付失败{}", e.getErrMsg());
            throw new ServiceException(e.getErrMsg());
        }
        if (response.isSuccess()) {
            log.info("调用成功" + response.getBody());
            return response.getBody();
        } else {
            log.error("调用失败" + response.getBody());
            return null;
        }
    }

    /**
     * 充值
     *
     * @param orderNo
     * @param totalFee
     * @return
     */
    @Override
    public String vipAppPay(String orderNo, Integer totalFee) {
        log.info("支付宝充值");
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content）
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("app支付");
        model.setSubject("橙果夜鱼快宿");
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(FormatUtils.fenToYuan(totalFee));
        request.setBizModel(model);
        request.setNotifyUrl(alipayAppConfig.getVipNotifyUrl());
        AlipayTradeAppPayResponse response;
        try {
            response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            log.error("支付宝支付失败{}", e.getErrMsg());
            throw new ServiceException(e.getErrMsg());
        }
        if (response.isSuccess()) {
            log.info("调用成功" + response.getBody());
            return response.getBody();
        } else {
            log.error("调用失败" + response.getBody());
            return null;
        }
    }

    /**
     * 推广充值
     *
     * @param orderNo
     * @param totalFee
     * @return
     */
    @Override
    public String rechangeAppPay(String orderNo, Integer totalFee) {
        log.info("支付宝推广充值");
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content）
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("app支付");
        model.setSubject("橙果夜鱼快宿");
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(FormatUtils.fenToYuan(totalFee));
        request.setBizModel(model);
        request.setNotifyUrl(alipayAppConfig.getRechangeNotifyUrl());
        AlipayTradeAppPayResponse response;
        try {
            response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            log.error("支付宝推广支付失败{}", e.getErrMsg());
            throw new ServiceException(e.getErrMsg());
        }
        if (response.isSuccess()) {
            log.info("推广调用成功" + response.getBody());
            return response.getBody();
        } else {
            log.error("推广调用失败" + response.getBody());
            return null;
        }
    }

    @Override
    public Boolean tradeRefund(String orderNo, Integer refundFee) {
        log.info("支付宝退款 {}");
        String outRequestNo = orderNo + RefundRequestNo.outNo;
        AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(orderNo);
        model.setRefundAmount(FormatUtils.fenToYuan(refundFee));
        model.setRefundReason("正常退款");
        model.setOutRequestNo(outRequestNo);
        refundRequest.setBizModel(model);
        AlipayTradeRefundResponse response;
        try {
            response = alipayClient.execute(refundRequest);
        } catch (AlipayApiException e) {
            log.error("支付宝退款失败{}", e.getLocalizedMessage());
            return false;
        }
        if (response != null && response.getCode().equals("10000")) {
            log.info("调用成功" + response);
            return true;
        } else {
            log.error("调用失败" + response);
            return false;
        }
    }


}
